package org.mtmi.ui;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.mtmi.ui.drawables.ImageDrawable;

/**
 * Image registry and utilities.
 * <p>
 * Images must be disposed by calling {@link #dispose()} method.
 */
public class IMG 
{

	public static final String I_Z_ORDER = "icons/z_order.png"; //$NON-NLS-1$
	public static final String I_TRACKPAD = "icons/trackpad.png"; //$NON-NLS-1$
	
	public static final String I_EQUALIZER = "icons/equalizer.png"; //$NON-NLS-1$
	public static final String I_KEYBOARD= "icons/keyboard.png"; //$NON-NLS-1$
	public static final String I_TRUMPET = "icons/trumpet48.png"; //$NON-NLS-1$
	public static final String I_KNOB_PROGRESSIF = "icons/knob_p.png"; //$NON-NLS-1$
	public static final String I_KNOB_SYMETRIC = "icons/knob_s.png"; //$NON-NLS-1$
	public static final String I_SPINNER= "icons/spinner.png"; //$NON-NLS-1$
	public static final String I_SLIDER_H= "icons/slider_h.png"; //$NON-NLS-1$
	public static final String I_SLIDER_V= "icons/slider_v.png"; //$NON-NLS-1$
	
	public static final String I_SCENE= "icons/scene.png"; //$NON-NLS-1$
	public static final String I_NEXT_SCENE= "icons/next_scene.png"; //$NON-NLS-1$
	public static final String I_PREV_SCENE= "icons/prev_scene.png"; //$NON-NLS-1$
	public static final String I_FIRST_SCENE= "icons/first_scene.png"; //$NON-NLS-1$
	public static final String I_LAST_SCENE= "icons/last_scene.png"; //$NON-NLS-1$
	public static final String I_SCENE_ADD= "icons/scene_add.png"; //$NON-NLS-1$
	public static final String I_SCENE_DEL= "icons/scene_del.png"; //$NON-NLS-1$
	public static final String I_SCENE_CHANGE_ICON= "icons/scene_change_icon.png"; //$NON-NLS-1$
	
	public static final String I_EDIT = "icons/edit_24.png"; //$NON-NLS-1$
	public static final String I_PLAY = "icons/play_24.png"; //$NON-NLS-1$
	public static final String I_EXIT = "icons/exit.png"; //$NON-NLS-1$
	
	public static final String I_CONNECTOR_UP_BG = "icons/connector_up_bg.png"; //$NON-NLS-1$
	public static final String I_CONNECTOR_LEFT_BG = "icons/connector_left_bg.png"; //$NON-NLS-1$
	
	public static final String I_ORIENTATION= "icons/orientation.png"; //$NON-NLS-1$
	public static final String I_RANGE_VALUE = "icons/range_value.png"; //$NON-NLS-1$
	public static final String I_H_RANGE_VALUE = "icons/h_range_value.png"; //$NON-NLS-1$
	public static final String I_V_RANGE_VALUE = "icons/v_range_value.png"; //$NON-NLS-1$
	public static final String I_KNOB_TYPE   = "icons/knob_type_24.png"; //$NON-NLS-1$
	
	public static final String I_MIDI_PORT = "icons/midi_port.png"; //$NON-NLS-1$
	public static final String I_MIDI_CHANNEL = "icons/midi_channel.png"; //$NON-NLS-1$
	public static final String I_MIDI_INSTRUMENT = "icons/midi_instrument.png"; //$NON-NLS-1$
	public static final String I_MIDI_INSTRUMENT_24 = "icons/midi_instrument_24.png"; //$NON-NLS-1$
	public static final String I_MIDI_VELOCITY = "icons/midi_velocity.png"; //$NON-NLS-1$
	public static final String I_MIDI_CONTROLLER= "icons/midi_controller.png"; //$NON-NLS-1$
	public static final String I_MIDI_VALUE= "icons/midi_value.png"; //$NON-NLS-1$

	public static final String I_CURVE_RESET= "icons/curve_reset.png"; //$NON-NLS-1$
	public static final String I_CURVE_RESET_REV= "icons/curve_reset_rev.png"; //$NON-NLS-1$
	public static final String I_CURVE_VSWAP= "icons/curve_vswap.png"; //$NON-NLS-1$
	public static final String I_CURVE_HSWAP= "icons/curve_hswap.png"; //$NON-NLS-1$
	
	private static HashMap<String,Image> registry;
	
	public static void dispose()
	{
		for( Map.Entry<String,Image> E : registry.entrySet() ) {
			E.getValue().dispose();
		}
		registry.clear();
		registry = null;
	}
	
	private static final String PATH = "../../../"; //$NON-NLS-1$
	
	/** @return the image from key, null if image does not exists */
	public static Image Get( String key )
	{
		if( registry!=null ) {
			Image img = registry.get( key );
			if( img!=null ) return img;
		}
		
		//              ui/mtmi/org
		String rname = PATH+key; 
		InputStream is = IMG.class.getResourceAsStream( rname );
		if( is==null ) return null;
		
		Image img = new Image( Display.getDefault(), is );
		if( img==null ) return null;
		
		if( registry==null ) {
			registry = new HashMap<String, Image>();
		}
		registry.put( key, img );
		
		return img;
	}
	
	/** @return IDrawable for given image key, or null if image does not exists */
	public static ImageDrawable GetD( String key ) {
		Image img = Get( key );
		if( img!=null ) {
			return new ImageDrawable( img );
		} else {
			return null;
		}
	}
	
	/** @return IDrawable for given image key, or null if image does not exists */
	public static ImageDrawable GetD( String key, float scale ) {
		String ikey = key+"scale:"+scale;
		Image img = Get( ikey );
		if( img!=null ) {
			return new ImageDrawable( img );
		} else {
			//not yet scaled ?
			img = Get( key );
			if( img==null ) {
				//image does not exists
				return null;
			} else {
				Rectangle bi = img.getBounds();
				int nw = Math.round( bi.width * scale );
				int nh = Math.round( bi.height * scale );
				Image scaled = new Image( img.getDevice(), nw, nh );
				GC gc = new GC( scaled );
				try {
					gc.drawImage( img, 0,0,bi.width,bi.height, 0,0,nw,nh );
				} finally {
					gc.dispose();
				}
				registry.put( ikey, scaled );
				return new ImageDrawable( scaled );
			}
		}
	}
	
	/** @return the list of available icons keys (from icons/scenes/contents.txt) */
	public static List<String> GetSceneIconKeys() {
		return GetImageKeys( "icons/scenes/" );
	}
	
	/** @return the list of available icons keys (from icons/scenes/contents.txt) */
	public static List<String> GetSceneBackgroundKeys() {
		return GetImageKeys( "icons/scenes/bg/" );
	}
	
	/** @return the list of available image in root directory, from file 'contents.txt' */
	private static List<String> GetImageKeys( String root )
	{
		String rname = PATH+root+"contents.txt"; //$NON-NLS-1$
		InputStream is = IMG.class.getResourceAsStream( rname );
		if( is==null ) throw new Error("cannot get images list from: '"+rname+"'");
		ArrayList<String> keys = new ArrayList<String>();
		InputStreamReader r = new InputStreamReader( is );
		BufferedInputStream bis = new BufferedInputStream( is, 4096 );
		StringBuilder sb = new StringBuilder();
		int c;
		try {
			while( (c=r.read())>0 ) {
				if( c=='\r' || c=='\n' ) {
					if( sb.length()>0 ) {
						String key = root+sb.toString();
						if( Get( key ) !=null ) {
							keys.add( key );
						}
					}
					sb = new StringBuilder();
				} else {
					sb.append( (char)c );
				}
			}
			if( sb.length()>0 ) {
				String key = root+sb.toString();
				if( Get( key )!=null ) {
					keys.add( key );
				}
			}
			is.close();
			bis.close();
		} catch( IOException x ) {
			throw new Error(x);
		}
		return keys;
	}
}
